package com.pms.service;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.pms.authority.PermissionInfo;
import com.pms.constant.BaseConstants;
import com.pms.entity.BaseUserInfo;
import com.pms.entity.FrontUser;
import com.pms.entity.UserInfo;
import com.pms.exception.RRException;
import com.pms.jwt.JwtTokenUtil;
import com.pms.rpc.IUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zyl
 * @create 2017-07-20 14:12
 **/
@Service
@Component
public class AuthServiceImpl implements AuthService {
    private JwtTokenUtil jwtTokenUtil;
    private IUserService userService;

    @Value("${gate.jwt.expiration}")
    private Long expiration;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public AuthServiceImpl(
            JwtTokenUtil jwtTokenUtil,
            IUserService userService) {
        this.jwtTokenUtil = jwtTokenUtil;
        this.userService = userService;
    }


    @Override
    public String login(BaseUserInfo info) {
        String  token = jwtTokenUtil.generateToken(info);
        return token;
    }

    @Override
    public String refresh(String token,BaseUserInfo info) {
        String refreshedToken = null;
            String username = jwtTokenUtil.getUsernameFromToken(token);
            //未过期
            if (username!=null){
                if (jwtTokenUtil.canTokenBeRefreshed(token,info.getUpdTime())){//info.getUpdTime()用户的修改时间
                    refreshedToken=token;
                }else {
                    refreshedToken=jwtTokenUtil.refreshToken(token,info);
                }
            }else {
                refreshedToken=jwtTokenUtil.refreshToken(token,info);
            }
            redisTemplate.opsForValue().set(info.getUsername(), token,expiration , TimeUnit.SECONDS);
        return refreshedToken;
    }

    @Override
    public Boolean invalid(String token) {
       Boolean as=  jwtTokenUtil.invalid(token);
        return as;
    }

    @Override
    public FrontUser getUserInfo(String token,Integer menuType,String companyCode) {
        String username = jwtTokenUtil.getUsernameFromToken(token);
        if(username==null)
            throw new RRException("token过期请重新登录", 400);
        UserInfo user = userService.getUserByUsername(username,companyCode);
        if (null==user||null==user.getId()){throw new RRException("用户信息不存在", 400);}
        if (null==user||null==user.getGroupId()){throw new RRException("该账户还未分配权限,请先分配权限", 400);}
        FrontUser frontUser  = new FrontUser();
        BeanUtils.copyProperties(user,frontUser);
        List<PermissionInfo> permissionInfos = userService.getPermissionByUsername(username,menuType,companyCode);
        Stream<PermissionInfo> menus = permissionInfos.parallelStream().filter((permission) -> {
            return permission.getType().equals(BaseConstants.RESOURCE_TYPE_MENU);
        });
        frontUser.setMenus(menus.collect(Collectors.toList()));
        Stream<PermissionInfo> elements = permissionInfos.parallelStream().filter((permission) -> {
            return !permission.getType().equals(BaseConstants.RESOURCE_TYPE_MENU);
        });
        frontUser.setElements(elements.collect(Collectors.toList()));
        frontUser.setImg(user.getImg());
        return frontUser;
    }

    @Override
    public Boolean validate(String token,String resource, Integer menuType,String companyCode) {
        String username = jwtTokenUtil.getUsernameFromToken(token);
        if (username==null){return false;}
        UserInfo info = userService.getUserByUsername(username,companyCode);
        return info.getUsername().equals(username)//账号是否相同
                && !jwtTokenUtil.isTokenExpired(token)//过期时间小于当前时间验证token时间未过
                && validateResource(username,resource,menuType,companyCode);
    }

    public Boolean validateResource(String username, String resource, Integer menuType,String companyCode){
        String [] res = resource.split(":");
        final String requestUri = res[0];
        final String method = res[1];
        List<PermissionInfo> clientPermissionInfo = userService.getPermissionByUsername(username,menuType,companyCode);
        Collection<PermissionInfo> result = Collections2.filter(clientPermissionInfo, new Predicate<PermissionInfo>() {
            @Override
            public boolean apply(PermissionInfo permissionInfo) {
                String url = permissionInfo.getUri();
                String uri = url.replaceAll("\\{\\*\\}", "[a-zA-Z\\\\d]+");
                String regEx = "^" + uri + "$";
                return (Pattern.compile(regEx).matcher(requestUri).find() || requestUri.startsWith(url + "/"))
                        && method.equals(permissionInfo.getMethod());
            }
        });
        if (result.size() <= 0) {
            return false;
        }
        return true;
    }

    /**
     * 提供API 接口
     * @param token
     * @param companyCode
     * @return
     */
    public FrontUser getApiUserInfo(String token,String companyCode) {
        String username = jwtTokenUtil.getUsernameFromToken(token);
        if(username==null)
            throw new RRException("登录过期，请重新登录", 40101);
        UserInfo user = userService.getUserByUsername(username,companyCode);
        if (null==user||null==user.getId()){throw new RRException("用户信息不存在", 400);}
        if (null==user||null==user.getGroupId()){throw new RRException("该账户还未分配权限,请先分配权限", 400);}
        FrontUser frontUser  = new FrontUser();
        BeanUtils.copyProperties(user,frontUser);
        List<PermissionInfo> permissionInfos = userService.getApiPermissionByUsername(username,companyCode);
        Stream<PermissionInfo> menus = permissionInfos.parallelStream().filter((permission) -> {
            return permission.getType().equals(BaseConstants.RESOURCE_TYPE_MENU);
        });
        frontUser.setMenus(menus.collect(Collectors.toList()));
        Stream<PermissionInfo> elements = permissionInfos.parallelStream().filter((permission) -> {
            return !permission.getType().equals(BaseConstants.RESOURCE_TYPE_MENU);
        });
        frontUser.setElements(elements.collect(Collectors.toList()));
        frontUser.setImg(user.getImg());
        return frontUser;
    }



    @Override
    public FrontUser getSuperUser(String token) {
        String username = jwtTokenUtil.getUsernameFromToken(token);
        if(username==null)
            return null;
        UserInfo user = userService.getSuperUserByUsername(username);
        if (null==user||null==user.getId()){throw new RRException("用户信息不存在", 400);}
        FrontUser frontUser  = new FrontUser();
        BeanUtils.copyProperties(user,frontUser);
        List<PermissionInfo> permissionInfos = userService.getPermissionBysuperAdmin(username);
        Stream<PermissionInfo> menus = permissionInfos.parallelStream().filter((permission) -> {
            return permission.getType().equals(BaseConstants.RESOURCE_TYPE_MENU);
        });
        frontUser.setMenus(menus.collect(Collectors.toList()));
        Stream<PermissionInfo> elements = permissionInfos.parallelStream().filter((permission) -> {
            return !permission.getType().equals(BaseConstants.RESOURCE_TYPE_MENU);
        });
        frontUser.setElements(elements.collect(Collectors.toList()));
        frontUser.setImg(user.getImg());
        return frontUser;
    }
}
